package com.yh.csx.bsf.flow.engine.state;

import com.yh.csx.bsf.core.util.JsonUtils;
import com.yh.csx.bsf.core.util.StringUtils;
import com.yh.csx.bsf.flow.provider.enums.FlowStateEnum;
import com.yh.csx.bsf.flow.provider.enums.TaskStateEnum;
import com.yh.csx.bsf.flow.core.base.FlowException;
import com.yh.csx.bsf.flow.core.base.Model;
import com.yh.csx.bsf.flow.core.base.Variable;
import com.yh.csx.bsf.flow.core.db.DbHelper;
import com.yh.csx.bsf.flow.dao.dal.t_approve_log_dal;
import com.yh.csx.bsf.flow.dao.dal.t_flow_dal;
import com.yh.csx.bsf.flow.dao.dal.t_task_dal;
import com.yh.csx.bsf.flow.dao.model.auto.t_approve_log_model;
import com.yh.csx.bsf.flow.engine.api.CommonApi;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: chejiangyi
 * @version: 2019-10-28 18:38
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Slf4j
public class BaseNode extends BaseFlow{
    protected Map<String,Variable> flowVariables;
    protected Model.Node modelNode;
    protected Map<String,BaseNode> nodes;
    public String getName(){
        return "";
    }

    /**
     * 流程流转
     * */
    public void flow(int flowid){

    }

    protected BaseNode findNode(int flowid,String node){
        val item = nodes.get(node);
        if(item == null)
        {
            throw new StateEngineException(flowid,"未找到节点:"+node);
        }
        return item;
    }

    protected Variable findVariable(int flowid,String key){
        val item = flowVariables.get(key);
        if(item == null)
        {
            throw new StateEngineException(flowid,"未找到变量:"+key);
        }
        return item;
    }

    protected void beginScript(int flowid){
        logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" beginScript 开始");
        refreshFlowApprove(flowid);
        CommonApi.doScript(flowid,0,"",this.modelNode.getBeginScript(), flowVariables);
        updateFlowVariable(flowid,flowVariables.values());
        logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" beginScript 结束");
    }

    protected boolean route(int flowid,int taskid){
        return route(flowid,taskid,new ArrayList<>(),0);
    }

    protected boolean route(int flowid,int taskid,List<String> results,long batch_id){
        logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" route 开始");
        val routes = CommonApi.routeStr(flowid,taskid,this.modelNode.getRoutes(), results, flowVariables);
        logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" route -> "+ StringUtils.nullToEmpty(routes));
        //刷新节点信息
        refreshFlowApprove(flowid);
        if(routes!=null&&!routes .equals("")){
            var routelist = routes.split(",");
            for(var route:routelist) {
                val next = findNode(flowid,route);
                if (next == null) {
                    logFlowDebug(flowid, "节点:" + this.modelNode.getTitle() + " route 找不到路由节点" + route);
                    throw new StateEngineException(flowid,"找不到路由节点" + route);
                }
            }
            logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" route 结束脚本开始执行");
            CommonApi.doScript(flowid,taskid,routes,this.modelNode.getEndScript(), flowVariables);
            logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" route 结束脚本完成执行");
            updateFlowVariable(flowid,flowVariables.values());

            //人工节点:关闭当前节点所有任务
            if(this instanceof ManNode) {
                DbHelper.call((c) -> {
                    new t_task_dal().closedAllTasks(c,flowid,this.modelNode.getTitle(),batch_id,"系统");
                });
                refreshFlowApprove(flowid);
                logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" route 前关闭当前节点所有任务");
            }
            for(var route:routelist) {
                val next = findNode(flowid,route);
                next.flow(flowid);
            }
            return true;
        }
        logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" route -> 路由结果信息为空");
        return false;
    }

    protected void refreshFlowApprove(int flowid){
        updateFlowApprove(flowid);
        updateFlowState(flowid, FlowStateEnum.waiting.Value);
        logFlowDebug(flowid,"节点:"+this.modelNode.getTitle()+" route 更新flow节点信息");
    }


    protected boolean updateFlowApprove(int flowid){
        return DbHelper.get((c)-> {
            val tasks = new t_task_dal().getTasks(c,flowid, TaskStateEnum.waiting.Value);
            var approve_node = this.modelNode.getTitle();
            var approve_userno=""; 
            var approve_by="";
            if(tasks!=null)
            {
                approve_node = String.join(",",tasks.stream().map(t->t.flow_approve_node).distinct().collect(Collectors.toList()));
                approve_userno = String.join(",",tasks.stream().map(t->t.flow_approve_userno).distinct().collect(Collectors.toList()));
                approve_by = String.join(",",tasks.stream().map(t->t.flow_approve_by).distinct().collect(Collectors.toList()));
            }

            return new t_flow_dal().updateFlowApprove(c,flowid,approve_node,approve_userno,approve_by);
        });
    }

    protected boolean updateFlowVariable( int flowid,Collection<Variable> variables){
        for(val variable:variables){
            this.flowVariables.put(variable.getKey(),variable);
        }
        return DbHelper.get((c)-> new t_flow_dal().updateFlowVariable(c,flowid, JsonUtils.serialize(this.flowVariables.values())));
    }
    protected boolean updateFlowState(int flowid,int flow_state){
        return DbHelper.get((c)-> new t_flow_dal().updateFlowState(c,flowid,flow_state));
    }

    protected boolean addApproveLog(t_approve_log_model model){
        return DbHelper.get((c)-> new t_approve_log_dal().add(c,model));
    }

    protected FlowException filterException(int flowid,Exception e){
        if(!(e instanceof FlowException)) {
            val e2 = new StateEngineException(flowid,"flowid"+ flowid +"节点:" + this.modelNode.getTitle() + " 流转异常", e);
            return e2;
        }
        else
        {   return (FlowException)e;}
    }

}